package com.taxshare.gateway.filter;

import cn.hutool.json.JSONUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.taxshare.gateway.config.GateConfig;
import com.taxshare.gateway.constant.CommonConstant;
import com.taxshare.jwt.JwtHelper;
import com.taxshare.response.beans.Response;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import static com.taxshare.gateway.constant.ResultConstant.*;


@Component
@Slf4j
@DependsOn("gateConfig")
public class AdminAccessFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        //设置字符集
        ctx.getResponse().setCharacterEncoding(CommonConstant.CHARACTER_SET_UTF_8);
        HttpServletRequest request = ctx.getRequest();
        //获取请求路径
        final String requestUri = request.getRequestURI().substring(GateConfig.getPrefix().length());
        //白名单过滤
        if (isStartWith(requestUri)) {
            return null;
        }
        //校验令牌
        String accessToken = request.getHeader(CommonConstant.ACCESS_TOKEN);
        //刷新令牌
        String refreshToken = request.getHeader(CommonConstant.REFRESH_TOKEN);
        //如果请求头未携带令牌则尝试从参数获取
        if (accessToken == null) {
            accessToken = request.getParameter(CommonConstant.ACCESS_TOKEN);
        }
        if (refreshToken == null) {
            refreshToken = request.getParameter(CommonConstant.REFRESH_TOKEN);
        }
        //保存请求头信息
        ctx.addZuulRequestHeader(CommonConstant.ACCESS_TOKEN, accessToken);
        ctx.addZuulRequestHeader(CommonConstant.REFRESH_TOKEN, refreshToken);
        //用户信息
        try {
            JwtHelper.getInfoFromToken(accessToken);
        } catch (ExpiredJwtException e) {
            //令牌过期,则尝试解析刷新令牌
            try {
                JwtHelper.getInfoFromToken(refreshToken);
                //重新签发令牌标志
                ctx.getResponse()
                        .addHeader(CommonConstant.TOKEN_INVALID, CommonConstant.TOKEN_INVALID_VALUE);
            } catch (ExpiredJwtException ex) {
                //刷新令牌失效,则令牌过期
                setFailedRequest(RET_GAT_00001_CODE, RET_GAT_00001_DESC);
                return null;
            } catch (Exception exx) {
                setFailedRequest(RET_GAT_00002_CODE, RET_GAT_00002_DESC);
                return null;
            }
        } catch (Exception e) {
            setFailedRequest(RET_GAT_00002_CODE, RET_GAT_00002_DESC);
            return null;
        }
        //执行后续路由
        return null;
    }

    /**
     * URI是否以什么打头
     */
    private boolean isStartWith(String requestUri) {
        boolean flag = false;
        for (String s : GateConfig.getUri()) {
          /*  if (requestUri.startsWith(s)) {
                return true;
            }
            if(requestUri.endsWith(s)){
                return true;
            }*/
          //todo 为了方便查看swagger测试环境
          if(requestUri.contains(s)){
              return true;
          }
        }
        return flag;
    }

    /**
     * 网关抛异常
     */
    private void setFailedRequest(String code, String msg) {
        Response<Object> response = new Response<>(code, msg);
        String body = JSONUtil.toJsonStr(response);
        log.error(">>>>>>网关请求失败>>>>>：{}", body);
        RequestContext ctx = RequestContext.getCurrentContext();
        //设置返回字符集
        ctx.getResponse().setContentType("text/html;charset=UTF-8");
        ctx.setResponseStatusCode(RET_SYS_STATUS_200);
        if (ctx.getResponseBody() == null) {
            ctx.setResponseBody(body);
            //不执行后续的路由
            ctx.setSendZuulResponse(false);
        }
    }

}
